#include "chessgui.h"
#include "ChessGame.h"
#include "model/BoardEvent.h"
#include <QGridLayout>
#include <QImage>
#include <QLabel>
#include <stdlib.h>
#include <QMenu>
#include <QMenuBar>
#include <QMouseEvent>

namespace view
{
    ChessGUI::ChessGUI(ChessGame& ctrl, model::ChessBoard& board, QWidget *parent)
        : QMainWindow(parent), ctrl(ctrl), board(board), active(NULL), listener(new ChangeListener(this))
    {
        this->board.addBoardListener(listener);
        makeMenu();
        makeGrid();
        makeLabels();

    }

    ChessGUI::~ChessGUI()
    {
        delete listener;
    }

    void ChessGUI::restart()
    {
        reset();
        ctrl.newGame();
    }

    void ChessGUI::makeGrid()
    {
        setCentralWidget(new QWidget);
        QGridLayout* lay = new QGridLayout(centralWidget());
        lay->setSpacing(0);
        lay->setMargin(0);
        lay->setOriginCorner(Qt::BottomLeftCorner);
        vmap& tgrid = const_cast<vmap&>(grid);
        model::ChessBoard::const_map_iterator end = board.getGrid().end();
        for (model::ChessBoard::const_map_iterator i = board.getGrid().begin(); i != end; i++)
        {
            tgrid.insert(std::make_pair(i->first, new Square(i->first)));
            lay->addWidget(grid.at(i->first), i->first.row, i->first.col);
        }
    }

    void ChessGUI::makeMenu()
    {
        QMenu* game = menuBar()->addMenu(tr("&Game"));
        QAction* ngame = game->addAction(tr("&New Game"));
        ngame->setShortcut(QKeySequence(tr("F2")));
        ngame->connect(game, SIGNAL(triggered(QAction*)), this, SLOT(restart()));
    }

    void ChessGUI::makeLabels()
    {
        QGridLayout* lay = static_cast<QGridLayout*>(centralWidget()->layout());
        for (int i = 0; i < model::ChessBoard::SIZE; i++)
        {
            QLabel* l = new QLabel(QString().setNum(i+1));
            l->setAlignment(Qt::AlignCenter);
            l->setFixedWidth(18);
            lay->addWidget(l, i+1, 0);
            l = new QLabel(QString('A' + i));
            l->setAlignment(Qt::AlignCenter);
            l->setFixedHeight(18);
            lay->addWidget(l, 0, 'A' + i);
        }

    }

    void ChessGUI::reset()
    {
        for (std::set<Square*>::const_iterator i = valids.begin(); i != valids.end(); i++)
            (*i)->setState(DEFAULT);
        valids.clear();
        if (active)
        {
            active->setState(DEFAULT);
            active = NULL;
        }
    }

    void ChessGUI::ChangeListener::BoardChanged(const model::BoardEvent e) const
    {
        self->grid.at(e.loc)->setPiece(e.value);
    }

    ChessGUI::ChangeListener::ChangeListener(ChessGUI *const gui) : self(gui) {}

    void ChessGUI::mouseReleaseEvent(QMouseEvent* e)
    {
        Square* s = dynamic_cast<Square*>(childAt(e->pos()));
        if (s)
        {
            globals::cPiece pc;
            if (s == active || e->button() == Qt::RightButton)
                reset();
            else if (active && s->getState() == HIGHLIGHT)
            {
                Square* tmp = active;
                reset();
                board.movePiece(tmp->loc, s->loc);
                board.switchTurn();
            }
            else if ((pc = s->getPiece()) && pc->isLight == ctrl.isLightTurn())
            {
                reset();
                active = s;
                globals::moveSet moves = ctrl.getValidMoves(pc);
                for (globals::moveSet::element_type::const_iterator i = moves->begin(); i != moves->end(); i++)
                    (*valids.insert(valids.end(), grid.at(i->to)))->setState(HIGHLIGHT);
            }
        }
    }
}
